import { ElLoading, ElMessage } from 'element-plus'
import http from "@/router/http";
import { debounce } from "throttle-debounce"; //防抖
/**
 * 获取本周、本月、上月、本季度的开始日期、结束日期
*/
let now = new Date();             // 当前日期
let nowDayOfWeek = now.getDay();  // 今天本周的第几天
let nowDay = now.getDate();       // 当前日
let nowMonth = now.getMonth();    // 当前月
let nowYear = now.getYear();      // 当前年
nowYear += (nowYear < 2000) ? 1900 : 0;

let lastMonthDate = new Date();  // 上月日期
lastMonthDate.setDate(1);
lastMonthDate.setMonth(lastMonthDate.getMonth() - 1);
let lastYear = lastMonthDate.getYear();
let lastMonth = lastMonthDate.getMonth();
let nextMonthDate = now//下月日期
nextMonthDate.setDate(1);
nextMonthDate.setMonth(nextMonthDate.getMonth() + 1);
let nextMonth = nextMonthDate.getMonth();
// 获得某月的天数
const getMonthDays = (month) => {
    let monthStartDate = new Date(nowYear, month, 1);
    let monthEndDate = new Date(nowYear, month + 1, 1);
    let days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24);
    return days;
}

// 获得本季度的开始月份
const getQuarterStartMonth = () => {
    let quarterStartMonth = 0;
    if (nowMonth < 3) {
        quarterStartMonth = 0;
    }
    if (2 < nowMonth && nowMonth < 6) {
        quarterStartMonth = 3;
    }
    if (5 < nowMonth && nowMonth < 9) {
        quarterStartMonth = 6;
    }
    if (nowMonth > 8) {
        quarterStartMonth = 9;
    }
    return quarterStartMonth;
}

// 获得本周的开始日期
const getWeekDate = () => {
    let weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
    let weekEndDate = new Date(nowYear, nowMonth, nowDay + (7 - nowDayOfWeek));
    return [formatTime(weekStartDate), formatTime(weekEndDate)];
}

// 获得本月的开始日期
const getMonthDate = () => {
    let monthStartDate = new Date(nowYear, nowMonth, 1);
    let monthEndDate = new Date(nowYear, nowMonth, getMonthDays(nowMonth));
    return [formatTime(monthStartDate), formatTime(monthEndDate)];
}

// 获得上月时间
const getLastMonthDate = () => {
    let lastMonthStartDate = new Date(nowYear, lastMonth, 1);
    let lastMonthEndDate = new Date(nowYear, lastMonth, getMonthDays(lastMonth));
    return [formatTime(lastMonthStartDate), formatTime(lastMonthEndDate)];
}
// 获得下月时间
const getNextMonthDate = () => {
    let start = new Date(nowYear, nextMonth, 1);
    let end = new Date(nowYear, nextMonth, getMonthDays(nextMonth));
    return [formatTime(start), formatTime(end)];
}

// 获得本季度的日期
const getQuarterDate = () => {
    let quarterStartDate = new Date(nowYear, getQuarterStartMonth(), 1);
    let quarterEndMonth = getQuarterStartMonth() + 2;
    let quarterEndDate = new Date(nowYear, quarterEndMonth, getMonthDays(quarterEndMonth));
    return [formatTime(quarterStartDate), formatTime(quarterEndDate)]
}
// 获取本年
const getYearDate = () => {
    let start = new Date(nowYear, 0, 1)
    let end = new Date(nowYear, 11, 31)
    return [formatTime(start), formatTime(end)]
}
// 指定日期的前几天后几天
const getNextDate = (date, day) => {
    var dd = new Date(date);
    dd.setDate(dd.getDate() + day);
    var y = dd.getFullYear();
    var m = dd.getMonth() + 1 < 10 ? "0" + (dd.getMonth() + 1) : dd.getMonth() + 1;
    var d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate();
    const wekNum = {
        '0': '日',
        '1': '一',
        '2': '二',
        '3': '三',
        '4': '四',
        '5': '五',
        '6': '六'
    }
    const week = wekNum[dd.getDay()]
    return y + "-" + m + "-" + d + '-' + week;
}
// 日期转时间戳
const getUnixTime = (dateStr) => {
    let newstr = dateStr.replace(/-/g, '/')
    let date = new Date(newstr)
    let time_str = date.getTime()
    return time_str
    //  time_str.substr(0, 10)
}
//将时分秒转为时间戳
const time_to_sec = (time) => {
    if (time !== null) {
        var s = "";
        var hour = time.split(":")[0];
        var min = time.split(":")[1];
        var sec = time.split(":")[2];
        s = Number(hour * 3600) + Number(min * 60) + Number(sec);
        return s;
    }
}
/**
 * 格式化时间
 * @param {Date} date
 * @returns {string}
 */
const formatTime = date => {
    const year = date.getFullYear()
    const month = date.getMonth() + 1
    const day = date.getDate()
    const hour = date.getHours()
    const minute = date.getMinutes()
    const second = date.getSeconds()

    return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}

const formatNumber = n => {
    n = n.toString()
    return n[1] ? n : '0' + n
}

// 格式化金额
const money = (num, other = '￥') => {
    if (num === 0) {
        return other + Number(num).toFixed(2)
    }
    if (!num) {
        return num
    }
    const arr = Number(num).toFixed(2).toString().split('.')
    arr[0] = arr[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    const newVal = arr.join('.')
    return other + newVal
}
// 格式化金额(不带单位)
const money1 = (num) => {
    if (num === 0) {
        return Number(num).toFixed(2)
    }
    if (!num) {
        return num
    }
    const arr = Number(num).toFixed(2).toString().split('.')
    arr[0] = arr[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    const newVal = arr.join('.')
    return newVal
}
// 格式化小笔数金额，无千分位
const smallMoney = (num, other = '+') => {
    if (num === 0) {
        return other + Number(num).toFixed(2)
    }
    if (!num) {
        return num
    }
    const arr = Number(num).toFixed(2).toString()
    // console.log(other + arr)
    return other + arr
}

/**
 * 验证身份证
 * @param Idcard
 * @returns {boolean}
 */
const checkIdcard = (rule, value, callback) => {
    // 1 "验证通过!", 0 //校验不通过
    var format = /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/;
    if (value) { //号码规则校验
        if (!format.test(value)) {
            callback(new Error("身份证号码不合规"))
            return ElMessage.error('身份证号码不合规');
        } else {
            //区位码校验
            //出生年月日校验   前正则限制起始年份为1900;
            var year = value && value.substr(6, 4),//身份证年
                month = value && value.substr(10, 2),//身份证月
                date = value && value.substr(12, 2),//身份证日
                time = Date.parse(month + '-' + date + '-' + year),//身份证日期时间戳date
                now_time = Date.parse(new Date()),//当前时间戳
                dates = (new Date(year, month, 0)).getDate(),//身份证当月天数
                strBirthday = year + '-' + month + '-' + date;
            //计算年龄，小于14岁不让买票
            var birthDate = new Date(strBirthday);
            var nowDateTime = new Date();
            var age = nowDateTime.getFullYear() - birthDate.getFullYear();
            //再考虑月、天的因素;.getMonth()获取的是从0开始的，这里进行比较，不需要加1
            if (nowDateTime.getMonth() < birthDate.getMonth() || (nowDateTime.getMonth() == birthDate.getMonth() && nowDateTime.getDate() < birthDate.getDate())) {
                age--;
            }
            if (time > now_time || date > dates) {
                callback(new Error("出生日期不合规"))
            }
            //校验码判断
            var c = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);   //系数
            var b = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');  //校验码对照表

            var id_array = value.split("");
            var sum = 0;
            for (var k = 0; k < 17; k++) {
                sum += parseInt(id_array[k]) * parseInt(c[k]);
            }
            if (id_array[17].toUpperCase() != b[sum % 11].toUpperCase()) {
                callback(new Error("身份证校验码不合规"))
            }
            callback()
            return true
        }
    } else {
        callback()
        return
    }
};
// 校验小于14岁的不让买票
const checkIdcardYear = (rule, value, callback) => {
    // 1 "验证通过!", 0 //校验不通过
    if (value) { //号码规则校验
        // console.log(value);
        var format = /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2]))\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/;
        if (!format.test(value)) {
            callback(new Error("身份证号码不合规"))
            return ElMessage.error('身份证号码不合规');
        } else {
            //区位码校验
            //出生年月日校验   前正则限制起始年份为1900;
            var year = value && value.substr(6, 4),//身份证年
                month = value && value.substr(10, 2),//身份证月
                date = value && value.substr(12, 2),//身份证日
                time = Date.parse(month + '-' + date + '-' + year),//身份证日期时间戳date
                now_time = Date.parse(new Date()),//当前时间戳
                dates = (new Date(year, month, 0)).getDate(),//身份证当月天数
                strBirthday = year + '-' + month + '-' + date;
            if (time > now_time || date > dates) {
                callback(new Error("出生日期不合规"))
            }
            //计算年龄，小于14岁不让买票
            var birthDate = new Date(strBirthday);
            var nowDateTime = new Date();
            var age = nowDateTime.getFullYear() - birthDate.getFullYear();
            if (nowDateTime.getMonth() < birthDate.getMonth() || (nowDateTime.getMonth() == birthDate.getMonth() && nowDateTime.getDate() < birthDate.getDate())) {
                age--;
            }
            if (age < 14) {
                callback(new Error("未满14岁不可下单、拼场"))
            }
            //校验码判断
            var c = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);   //系数
            var b = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');  //校验码对照表

            var id_array = value.split("");
            var sum = 0;
            for (var k = 0; k < 17; k++) {
                sum += parseInt(id_array[k]) * parseInt(c[k]);
            }
            if (id_array[17].toUpperCase() !== b[sum % 11].toUpperCase()) {
                callback(new Error("身份证校验码不合规"))
            }
            const num = value.charAt(value.length - 2)
            let sex = ''
            if (num % 2 === 0) {
                sex = '1'
            } else {
                sex = '2'
            }
            return sex
        }
    } else {
        callback(new Error("请输入身份证号码"))
    }
};
// 港澳通行证
const isHKCard = (card) => {
    // 港澳居民来往内地通行证
    // 规则： H/M + 10位或6位数字
    // 样本： H1234567890
    var reg = /^([H|h|M|m](\d{6}|\d{10}))$/;
    if (reg.test(card) === false) {
        return ElMessage.error('港澳居民来往内地通行证号码不合规');
    } else {
        return true
    }
}
// 台湾通行证
const isTWCard = (card) => {
    // 台湾居民来往大陆通行证
    // 规则： 新版8位或18位数字， 旧版10位数字 + 英文字母
    // 样本： 12345678 或 1234567890B
    var reg = /^((\d{8}|\d{18})|^\d{10}[a-zA-Z])$/
    if (reg.test(card) === false) {
        return ElMessage.error('台湾居民来往大陆通行证号码不合规');
    } else {
        return true
    }
}
const isPassPortCard = (card) => {
    // 护照
    // 规则： 14/15开头 + 7位数字, G + 8位数字, P + 7位数字, S/D + 7或8位数字,等
    // 样本： 141234567, G12345678, P1234567
    var reg = /^1[45][0-9]{7}$|([P|p|S|s]\d{7}$)|([S|s|G|g]\d{8}$)|([Gg|Tt|Ss|Ll|Qq|Dd|Aa|Ff]\d{8}$)|([H|h|M|m](\d{8}|\d{10}))$/;
    if (reg.test(card) === false) {
        return ElMessage.error('护照号码不合规');
    } else {
        return true
    }
}

const checkPhone = (rule, value, callback) => {
    if (value && !(/^1[3456789]\d{9}$/.test(value))) {
        ElMessage.error('手机号码格式错误');
        callback(new Error('手机号码格式错误'));
        return false
    } else {
        callback()
        return true
    }

};

const checkNUMBER = (rule, value, callback) => {
    if (!value) {
        return callback(new Error('请输入'))
    } else {
        // console.log(Number(value), Number(value) > 0);
        setTimeout(() => {
            if (!Number(value)) {
                callback(new Error('请输入数字'))
            } else if (Number(value) < 0) {
                callback(new Error('请输入正数'))
            } else if (value.toString().split('.')[1]) {
                if (value.toString().split('.')[1].length > 2) {
                    callback(new Error('最多输入两位小数'))
                } else {
                    callback()
                }
            } else {
                callback()
            }
        }, 300)
    }
}

/**
 * 信息脱敏
 * @param {string} value
 * @returns {boolean}
 */
const checkId = (value) => {
    //数字从第四位至倒数第四位脱敏
    var val = ''
    if (value.length > 0) {
        if (10 < value.length <= 18)
            val = value.substring(0, 4) + '******' + value.substring(value.length - 8);
        else if (value.length <= 9)
            // console.log(value.substring(0, 3))
            val = value.substring(0, 3) + '***' + value.substring(value.length - 3);
    }
    return val;
}

/**
 * 中文姓名验证
 * @param {string} value
 * @returns {boolean}
 */
const checkName = (rule, value, callback) => {
    const check = /^([\u4e00-\u9fa5]{2,20}|[a-zA-Z.\s]{2,20})$/
    if (value && !check.test(value)) {
        ElMessage.error('姓名不能包含数字及特殊字符');
        callback(new Error('姓名不能包含数字及特殊字符'));
        return false
    } else {
        callback();
        return true
    }
}
const checkUnZh = (rule, value, callback) => {
    const check = /^[^\u4e00-\u9fa5]*$/
    if (value && !check.test(value)) {
        ElMessage.error('请勿输入汉字');
        callback(new Error('请勿输入汉字'));
        return false
    } else {
        callback();
        return true
    }
}
/**
 * 邮箱地址验证
 * @param {string} value
 * @returns {boolean}
 */
const checkMail = (value) => {
    const check = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
    if (value && !check.test(value)) {
        ElMessage.error('请输入正确的邮箱地址');
        return false
    } else {
        return true
    }
}
/**
 * 统一信用码
 */
const creditCode = (rule, value, callback) => {
    const check = /^[^_IOZSVa-z\W]{2}\d{6}[^_IOZSVa-z\W]{10}$/
    if (value && !check.test(value)) {
        callback(new Error('请输入正确的统一信用码'));
    } else {
        callback();
    }
};

/**
 * 字符限制
 */
const characterLimit = (rule, value, callback) => {
    var len = 0;
    if (value) {
        for (var i = 0; i < value.length; i++) {
            var c = value.charCodeAt(i);
            //单字节加1
            if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
                len++;
            } else {
                len += 2;
            }
        }
        if (len > 30) {
            //重点重点，下面就是填写提示的文字
            callback(new Error("主菜单名字不多于15个汉字或30个字符"));
        } else {
            callback();
        }
    } else {
        callback();
    }
}

const formatTimeToYYYYMMDDHHMMSS = (date) => {
    // 提取年、月、日、小时、分钟和秒
    var year = date.getFullYear();
    var month = ('0' + (date.getMonth() + 1)).slice(-2);
    var day = ('0' + date.getDate()).slice(-2);
    var hours = ('0' + date.getHours()).slice(-2);
    var minutes = ('0' + date.getMinutes()).slice(-2);
    var seconds = ('0' + date.getSeconds()).slice(-2);
    // 格式化时间字符串
    var formattedTime = year + month + day + hours + minutes + seconds;
    return formattedTime;
}
/* 
    获取七牛云token
*/
const getQiNiuToken = () => {
    // 提取年、月、日、小时、分钟和秒
    let token = sessionStorage.getItem('token-qiniu')
    const expires = sessionStorage.getItem('qiniu-expires-in')
    if (new Date().getTime() - expires > 1000 * 60 * 58) { //重新获取
        return new Promise((resolve, reject) => {
            http.get('/linkon-lianpeng/admin/LIAN_PENG/general/upload/getQiNiuToken', {}).then((res) => {
                sessionStorage.setItem('token-qiniu', res.data)
                sessionStorage.setItem('qiniu-expires-in', new Date().getTime())
                resolve(res.data)
            }).catch(err => {
                console.log(err);
                reject(err)
            });
        })
    } else {
        return token;
    }
}

//下载url文件
const downLoadUrl = (url) => {
    if (!url) {
        ElMessage.error('资源为空，不可下载~')
        return false
    }
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.onload = function () {
        if (xhr.status === 200) {
            var contentType = xhr.getResponseHeader('Content-Type');
            console.log(contentType)
            let suffix = ''
            if (contentType.indexOf('rar') !== -1) {
                suffix = '.rar'
            } else if (contentType.indexOf('zip') !== -1) {
                suffix = '.zip'
            } else if (contentType.indexOf('pdf') !== -1) {
                suffix = '.pdf'
            }
            var blob = xhr.response;
            var link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);
            link.setAttribute('download', name + suffix);
            link.click();
        }
    };
    xhr.send();
}


const characterLimitTwenty = (rule, value, callback) => {
    var len = 0;
    if (value) {
        for (var i = 0; i < value.length; i++) {
            var c = value.charCodeAt(i);
            //单字节加1
            if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
                len++;
            } else {
                len += 2;
            }
        }
        if (len > 40) {
            //重点重点，下面就是填写提示的文字
            callback(new Error("不多于20个汉字或40个字符"));
        } else {
            callback();
        }
    } else {
        callback();
    }
}
/**
 * 导出函数
 * condition:参数 
 * url接口地址
 * text下载文本
 */
const expExcel = debounce(300, async (condition, url, text) => {
    if (url) {
        const loading = ElLoading.service({
            lock: true,
            text: 'Loading',
            background: 'rgba(0, 0, 0, 0.7)',
        })
        condition.responseType = 'blob'//需带responseType参数进去
        await http.post(url, condition).then(res => {
            var blob = new Blob([res]);
            const url = URL.createObjectURL(blob);
            let element = document.createElement("a");
            element.download = text + '.xlsx';
            element.style.display = 'none';
            element.href = url
            document.body.appendChild(element);
            element.click();
            URL.revokeObjectURL(element.href);
            document.body.removeChild(element)
            setTimeout(() => { loading.close() }, 1000)
        }).catch(err => {
            setTimeout(() => { loading.close() }, 1000)
        })
    } else {
        ElMessage('暂未实现')
    }
})
// 手动实现 UTF-8 解码
const utf8ArrayToString = (bytes) => {
    let str = "";
    let i = 0;
    while (i < bytes.length) {
        const byte = bytes[i];
        if (byte < 0x80) {
            // 1 字节字符 (ASCII)
            str += String.fromCharCode(byte);
            i++;
        } else if ((byte & 0xe0) === 0xc0) {
            // 2 字节字符
            str += String.fromCharCode(((byte & 0x1f) << 6) | (bytes[i + 1] & 0x3f));
            i += 2;
        } else if ((byte & 0xf0) === 0xe0) {
            // 3 字节字符
            str += String.fromCharCode(
                ((byte & 0x0f) << 12) |
                ((bytes[i + 1] & 0x3f) << 6) |
                (bytes[i + 2] & 0x3f)
            );
            i += 3;
        } else {
            // 4 字节字符（需代理对处理，此处简化）
            i += 4; // 跳过处理复杂字符
        }
    }
    return str;
};
const parseMarkdown = (content) => {
    // 自定义解析规则
    return content
        // 处理标题
        .replace(/^###\s+(.+)$/gm, '<h3 class="wx-h3"><span class="wx-h3-prefix">###</span>$1</h3>')
        // 处理无序列表
        .replace(/^-\s+(.+)$/gm, '<li class="wx-list-item">• $1</li>')
        // 处理加粗文本
        .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
        // 处理换行
        .replace(/\n/g, '<br>')
        // 包裹列表项
        .replace(/<li/g, '<ul class="wx-list"><li')
        .replace(/<\/li>/g, '</li></ul>');
};
const formaNum=(num)=>{
    if (!num) {
        return 0
    }
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
const getUrlParam = (name) => {
    let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    let r = window.location.search.substr(1).match(reg);
    if (r != null) {
        return unescape(r[2]);
    }
    return null;
}
export {
    formatTime,
    money,
    money1,
    smallMoney,
    checkIdcard,
    isHKCard,
    isTWCard,
    isPassPortCard,
    checkPhone,
    checkId,
    checkName,
    getUnixTime,
    time_to_sec,
    checkMail,
    creditCode,
    characterLimit,
    checkUnZh,
    checkIdcardYear,
    checkNUMBER,
    downLoadUrl,
    getQiNiuToken,
    formatTimeToYYYYMMDDHHMMSS,
    characterLimitTwenty,
    getMonthDays,
    getQuarterStartMonth,
    getWeekDate,
    getMonthDate,
    getLastMonthDate,
    getQuarterDate,
    getYearDate,
    getNextMonthDate,
    getNextDate,
    expExcel, 
    utf8ArrayToString,
    parseMarkdown,
    formaNum,
    getUrlParam
}